package com.base.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


@Slf4j
public class TimeUtils {

    /**
     * DateTimeFormatter缓存
     */
    private static Map<String, DateTimeFormatter> DATE_TIME_FORMATTER_CACHE = new ConcurrentHashMap();

    private static final List<String> FORMARTS = new ArrayList<>(4);

    {
        FORMARTS.add("yyyy-MM");
        FORMARTS.add("yyyy-MM-dd");
        FORMARTS.add("yyyy-MM-dd HH:mm");
        FORMARTS.add("yyyy-MM-dd HH:mm:ss");
    }

    /**
     * DateTimeFormatter缓存的最大值
     */
    private static final int MAX_CACHE_SIZE = 32;

    public static LocalDate dateToLocalDate(Date date) {
        return dateToLocalDateTime(date).toLocalDate();
    }

    public static LocalDateTime dateToLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone);
    }

    private static String formatLocalDate(LocalDate localDate, DateTimeFormatter dateTimeFormatter) {
        return localDate.format(dateTimeFormatter);
    }

    public static String formatLocalDate(LocalDate localDate, String format) {
        return formatLocalDate(localDate, getDateTimeFormatter(format));
    }

    public static LocalDate parseLocalDate(String value, String format) {
        return LocalDate.parse(value, getDateTimeFormatter(format));
    }

    public static String formatDate(Date date, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }

    private static DateTimeFormatter getDateTimeFormatter(String format) {
        clearCacheIfTooMany();
        DateTimeFormatter dateTimeFormatter = DATE_TIME_FORMATTER_CACHE.get(format);
        if (Objects.isNull(dateTimeFormatter)) {
            dateTimeFormatter = DateTimeFormatter.ofPattern(format);
            DATE_TIME_FORMATTER_CACHE.put(format, dateTimeFormatter);
        }
        return dateTimeFormatter;
    }

    private static void clearCacheIfTooMany() {
        if (DATE_TIME_FORMATTER_CACHE.size() > MAX_CACHE_SIZE) {
            DATE_TIME_FORMATTER_CACHE.clear();
        }
    }
}
